----------------------------------------------------------------------------------
-- Company: 
-- Engineer: Siebe Krijgsman
-- 
-- Create Date:    22:42:49 12/03/2008 
-- Design Name: 
-- Module Name:    key_reader - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity key_reader is
    Port ( 	clk		: in std_logic;
				reset		: in std_logic;
	 
				KBD_CLOCK : in  STD_LOGIC;
				KBD_DATA : in  STD_LOGIC;
				
				key_data : out  STD_LOGIC_VECTOR(7 downto 0);
				data_valid : out std_logic);
end key_reader;

architecture Behavioral of key_reader is
	signal read_buffer 	: std_logic_vector(7 downto 0) := (others => '0');
	signal state			: integer := 0;
	signal parity			: std_logic := '0';
	signal data_valid_i	: std_logic := '0';
	signal counter			: std_logic_vector(1 downto 0) := "00";
begin
	
	process (clk, reset)
	begin
		if reset = '0' then
			key_data 	<= (others => '0');
			data_valid 	<= '0';
		elsif clk'event and clk = '1' then
			if data_valid_i = '1' and counter = "00" then
				key_data 	<= read_buffer;
				data_valid 	<= '1';
				counter 		<= "01";
			elsif counter = "01" then			--keep the data_valid for 3 cycles
				counter <= "10";
			elsif counter = "10" then			--keep the data_valid for 3 cycles
				counter <= "11";
			else
				data_valid <= '0';
				if data_valid_i = '0' then		--continue only after the next read cycle has started
					counter <= "00";
				end if;
			end if;
		end if;
	end process;
	
	process (KBD_CLOCK)
	begin
		if KBD_CLOCK'event and KBD_CLOCK = '1' then
			if state = 0 then
				if KBD_DATA = '0' then					--start bit (should be '0')
					state <= 1;
					data_valid_i <= '0';
					read_buffer <= (others => '0');
				end if;
				--reset internal
				parity <= '0';
				--data_valid_i <= '1';
			elsif state = 1 then
				read_buffer(0) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 2;
			elsif state = 2 then
				read_buffer(1) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 3;
			elsif state = 3 then
				read_buffer(2) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 4;
			elsif state = 4 then
				read_buffer(3) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 5;
			elsif state = 5 then
				read_buffer(4) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 6;
			elsif state = 6 then
				read_buffer(5) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 7;
			elsif state = 7 then
				read_buffer(6) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 8;
			elsif state = 8 then
				read_buffer(7) <= KBD_DATA;
				data_valid_i <= '0';
				state <= 9;
			elsif state = 9 then
				parity <= 	read_buffer(0) xor 
								read_buffer(1) xor 
								read_buffer(2) xor 
								read_buffer(3) xor 
								read_buffer(4) xor 
								read_buffer(5) xor 
								read_buffer(6) xor 
								read_buffer(7) xor
								KBD_DATA;			--calculate parity bit
				state <= 10;
			elsif state = 10 then
				if KBD_DATA = '1' and parity = '1' then			--stop bit (should be '1')
					data_valid_i <= '1';
				else
					data_valid_i <= '0';
				end if;
				state <= 0;
			end if;
		end if;
	end process;

end Behavioral;
